package com.cloudkinto.service.detective.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.dto.stock.query.SkuStockPageDto;
import com.cloudkinto.enumType.stock.StockOrderTypeEnum;
import com.cloudkinto.enumType.stock.StockTypeEnum;
import com.cloudkinto.common.DynamicTablePolicy;
import com.cloudkinto.common.common.DateUtils;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.dict.StaticDict;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.*;
import com.cloudkinto.dto.print.DefectiveTableDto;
import com.cloudkinto.dto.print.common.DynamicTableDto;
import com.cloudkinto.dto.stock.adjust.sku.SkuCellStockDto;
import com.cloudkinto.dto.stock.defective.SkuPickQueryBo;
import com.cloudkinto.dto.stock.defective.SkuStockForPickDto;
import com.cloudkinto.dto.stock.defective.SkuStockTotalDto;
import com.cloudkinto.dto.stock.stock.StockPickDto;
import com.cloudkinto.dto.stock.stock.StockPickListDto;
import com.cloudkinto.entity.*;
import com.cloudkinto.service.detective.vo.StartPickReq;
import com.cloudkinto.service.detective.vo.pick.BatchReq;
import com.cloudkinto.service.detective.vo.pick.PickInfoRes;
import com.cloudkinto.service.detective.vo.pick.PickSkuInfoRes;
import com.cloudkinto.service.detective.vo.pick.PickSkuRackInfo;
import com.cloudkinto.service.detective.vo.shelf.SubmitShelfInitRes;
import com.cloudkinto.service.detective.vo.shelf.SubmitShelfSkuRackRes;
import com.cloudkinto.service.detective.vo.shelf.SubmitShelfSkuRes;
import com.cloudkinto.service.order.returns.OrderReturnService;
import com.cloudkinto.service.stock.ProductStockFlowingService;
import com.cloudkinto.service.stock.ProductStockService;
import com.cloudkinto.service.stock.StockPickingService;
import com.cloudkinto.service.storage.StorageLocationService;
import com.cloudkinto.utils.AsposePdfUtils;
import com.cloudkinto.utils.BarCodeUtils;
import com.cloudkinto.utils.BeanCopierUtils;
import com.cloudkinto.vo.defective.*;
import com.cloudkinto.service.company.CompanyService;
import com.cloudkinto.service.detective.DefectiveService;
import com.cloudkinto.service.file.FileMoreService;
import com.cloudkinto.vo.file.FileMsg;
import com.cloudkinto.vo.file.FileRes;
import com.cloudkinto.vo.order.returns.OrProgressRes;
import com.cloudkinto.service.warehouse.WarehouseService;
import com.cloudkinto.vo.stock.ProductFlowingInEt;
import com.cloudkinto.vo.stock.ProductFlowingOutEt;
import com.cloudkinto.vo.storage.LocationRes;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.data.*;
import com.deepoove.poi.util.PoitlIOUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * <p>
 * service实现类
 * </p>
 *
 * @author hua
 * @since 2024-12-11
 */
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)//事务回滚
public class DefectiveServiceImpl extends ServiceImpl<DefectiveDao, DefectiveDo> implements DefectiveService {
    private final DefectiveDao dao;
    private final CompanyService companyService;
    private final WarehouseService warehouseService;
    private final FileMoreService fileMoreService;
    private final DefectiveProductDao defectiveProductDao;
    private final ProductStockService productStockService;
    private final ProductStockRackDao productStockRackDao;
    private final StockPickingService stockPickingService;
    private final StockPickingDao stockPickingDao;
    private final ProductDao productDao;
    private final ProductStockDao productStockDao;
    private final StorageLocationService storageLocationService;
    private final ProductStockFlowingService productStockFlowingService;
    @Value("${gbc.template.filePath}")
    private String templatePath;
    @Value("${gbc.template.localPath}")
    private String localPath;
    private final OrderReturnService orderReturnService;
    @Override
    public SingleResult addInit() {
        return SingleResult.success("");
    }

    @Override
    public Object add(DefectiveAddReq req, Long userId, Long companyId, Long tenantId) {
        //先判断库存够不够
        if (checkStock(companyId, tenantId, req.getProducts(), req.getPush(), req.getWhId())) {
            throw new BizException(SysConstant.Sku_Stock_NotEnough, "sku");
        }

        DefectiveDo entityDo = new DefectiveDo();
        BeanUtils.copyProperties(req, entityDo);
        int count = dao.getCount(companyId);
        count++;
        StringBuilder returnNo = new StringBuilder(count + "");
        while (returnNo.length() < 4) {
            returnNo.insert(0, 0);
        }
        CompanyDo companyDo = companyService.getById(companyId);
        returnNo.insert(0, DateUtils.dateFormatToString(new Date(), "yyMMdd")).insert(0, companyDo.getCompanyCode()).insert(0, "DPR");
        entityDo.setDefectiveNo(returnNo.toString());
        if (req.getPush() == 0) {
            entityDo.setOmsStatus(StaticDict.Defective_Oms_Status.First.getValue());
        }
        else {
            entityDo.setOmsStatus(StaticDict.Defective_Oms_Status.Second.getValue());
            entityDo.setWmsStatus(StaticDict.Defective_Wms_Status.First.getValue());
            entityDo.setSubmitBy(userId);
            entityDo.setSubmitTime(new Date());
        }
        dao.insert(entityDo);

        Map<Long, List<DefectiveProductAddReq>> productAddMap = req.getProducts().stream().collect(Collectors.groupingBy(DefectiveProductAddReq::getProductId));
        for (Long productId : productAddMap.keySet()) {
            DefectiveProductDo productDo = new DefectiveProductDo(entityDo.getId(), productId, productAddMap.get(productId).stream().mapToInt(DefectiveProductAddReq::getQuantity).sum());
            defectiveProductDao.insert(productDo);
        }

        this.lockStock(companyId, tenantId, entityDo, req.getProducts(), req.getPush(), req.getWhId());
        if (req.getFiles() != null) {
            //主表附件
            List<Long> fileIds = req.getFiles().stream().map(FileMsg::getFileId).filter(Objects::nonNull).collect(Collectors.toList());
            fileMoreService.insertFileMoreList(fileIds, entityDo.getId(), StaticDict.File_Type.Defective.getValue(), userId, null);
        }
        return entityDo.getId();
    }



    @Override
    public Object update(DefectiveUpdateReq req, Long userId, Long companyId, Long tenantId) {
        DefectiveDo entityDo = dao.selectById(req.getId());
        if (entityDo == null) {
            throw new BizException(SysConstant.No_Data);
        }
        if (!StaticDict.Defective_Oms_Status.First.getValue().equals(entityDo.getOmsStatus())) {
            throw new BizException(SysConstant.NoPower);
        }
        //先判断库存够不够
        if (checkStock(companyId, tenantId, req.getProducts(), req.getPush(), req.getWhId())) {
            throw new BizException(SysConstant.Sku_Stock_NotEnough,"sku");
        }
        BeanUtils.copyProperties(req, entityDo);
        if (req.getPush() == 1) {
            entityDo.setOmsStatus(StaticDict.Defective_Oms_Status.Second.getValue());
            entityDo.setWmsStatus(StaticDict.Defective_Wms_Status.First.getValue());
            entityDo.setSubmitBy(userId);
            entityDo.setSubmitTime(new Date());
        }
        dao.updateById(entityDo);
        defectiveProductDao.updateDelete(entityDo.getId(), userId);

        Map<Long, List<DefectiveProductAddReq>> productAddMap = req.getProducts().stream().collect(Collectors.groupingBy(DefectiveProductAddReq::getProductId));
        for (Long productId : productAddMap.keySet()) {
            DefectiveProductDo productDo = new DefectiveProductDo(entityDo.getId(), productId, productAddMap.get(productId).stream().mapToInt(DefectiveProductAddReq::getQuantity).sum());
            defectiveProductDao.insert(productDo);
        }
        //提交了就要锁定库存
        this.lockStock(companyId, tenantId, entityDo, req.getProducts(), req.getPush(), req.getWhId());
        if (req.getFiles() != null) {
            List<Long> fileIds = req.getFiles().stream().filter(i -> i.getId() == null).map(FileMsg::getFileId).filter(Objects::nonNull).collect(Collectors.toList());
            fileMoreService.insertFileMoreList(fileIds, entityDo.getId(), StaticDict.File_Type.Defective.getValue(), userId, null);
        }
        return null;
    }

    /**
     * 锁定库存
     * @param companyId
     * @param tenantId
     * @param entityDo
     * @param products
     * @param push
     * @param whId
     */
    public void lockStock(Long companyId, Long tenantId, DefectiveDo entityDo, List<DefectiveProductAddReq> products, int push, Long whId) {
        if (push == 1) {
            //提交了就要锁定库存
            //按照库位优先级，先进先出 获取库存列表
            List<StockPickingDo> pickingList = new ArrayList<>();
            List<Long> productIds = products.stream().map(DefectiveProductAddReq::getProductId).collect(Collectors.toList());
            List<SkuStockForPickDto> stockForPickList = productStockService.getStockForPickList(new SkuPickQueryBo(tenantId, companyId, 1, 1, whId, productIds));
            for (DefectiveProductAddReq product : products) {
                int quantity = product.getQuantity();
                if (quantity == 0) continue;
                for (SkuStockForPickDto i : stockForPickList) {
                    if (!(Objects.equals(i.getProductId(), product.getProductId()) && i.getQuantity() > 0)) continue;
                    int lockQty = 0;
                    if (i.getQuantity() > quantity) {
                        lockQty = quantity;
                        quantity = 0;
                    }
                    else {
                        lockQty = i.getQuantity();
                        quantity -= lockQty;
                    }
                    if (lockQty == 0) {
                        continue;
                    }
                    i.setQuantity(i.getQuantity() - lockQty);
                    productStockRackDao.lockStock(i.getStockId(), lockQty);
                    //添加到锁定记录
                    StockPickingDo pickingDo = new StockPickingDo(whId, entityDo.getId(),
                            StaticDict.Stock_Pick_OrderType.Defective.getValue(), "sku", i.getProductId(), i.getRackId(), i.getStockId(), lockQty);
                    pickingList.add(pickingDo);
                }
                if (quantity > 0) {
                    throw new BizException(SysConstant.Sku_Stock_NotEnough, product.getSku());
                }
            }
            stockPickingService.insertBatch(pickingList);
        }
    }

    @Override
    public void submit(BatchReq req, Long userId, Long companyId, Long tenantId) {
        for (Long id : req.getIds()) {
            DefectiveDo entityDo = dao.selectById(id);
            if (entityDo == null || !Objects.equals(entityDo.getCompanyId(), companyId)) {
                continue;
            }
            if (!StaticDict.Defective_Oms_Status.First.getValue().equals(entityDo.getOmsStatus())) {
                continue;
            }
            List<DefProductDto> productDtoList = defectiveProductDao.getProducts(id);

            List<DefectiveProductAddReq> products = BeanCopierUtils.listCopyMapper(productDtoList, DefProductDto.class, DefectiveProductAddReq.class);
            if (this.checkStock(companyId, tenantId, products, 1, entityDo.getWhId())) {
                throw new BizException(SysConstant.Sku_Stock_NotEnough, "sku");
            }
            entityDo.setOmsStatus(StaticDict.Defective_Oms_Status.Second.getValue());
            entityDo.setWmsStatus(StaticDict.Defective_Wms_Status.First.getValue());
            entityDo.setSubmitBy(userId);
            entityDo.setSubmitTime(new Date());
            dao.updateById(entityDo);

            this.lockStock(companyId, tenantId, entityDo, products, 1, entityDo.getWhId());
        }
    }

    public boolean checkStock(Long companyId, Long tenantId, List<DefectiveProductAddReq> products, int push, Long whId) {
        List<Long> productIds = products.stream().map(DefectiveProductAddReq::getProductId).collect(Collectors.toList());
        if (productIds.isEmpty()) return true;
        if (push == 1) {
            List<SkuStockTotalDto> skuStockTotal = productStockService.getSkuStockTotal(new SkuPickQueryBo(tenantId, companyId, 1, 1, whId, productIds));
            Map<Long, SkuStockTotalDto> skuMap = skuStockTotal.stream().collect(Collectors.toMap(SkuStockTotalDto::getProductId, i -> i));
            for (DefectiveProductAddReq product : products) {
                SkuStockTotalDto skuTotal = skuMap.get(product.getProductId());
                if (skuTotal == null || skuTotal.getQuantity() < product.getQuantity()) {
                    throw new BizException(SysConstant.Sku_Stock_NotEnough, product.getSku());
                }
            }
        }
        return false;
    }


    @Override
    public void cancel(BatchReq req, Long userId, Long companyId) {
        for (Long id : req.getIds()) {
            DefectiveDo entityDo = dao.selectById(id);
            if (entityDo == null || !Objects.equals(entityDo.getCompanyId(), companyId)) {
                continue;
            }
            if (!StaticDict.Defective_Oms_Status.First.getValue().equals(entityDo.getOmsStatus()) && !StaticDict.Defective_Oms_Status.Second.getValue().equals(entityDo.getOmsStatus())) {
                continue;
            }
            entityDo.setOmsStatus(StaticDict.Defective_Oms_Status.Fourth.getValue());
            entityDo.setWmsStatus(StaticDict.Defective_Wms_Status.Fifth.getValue());
            entityDo.setCancelBy(userId);
            entityDo.setCancelTime(new Date());
            dao.updateById(entityDo);
            //去回滚锁定库存
            List<StockPickingDo> pickingDos = stockPickingService.lambdaQuery().eq(StockPickingDo::getOrderId, id)
                    .eq(StockPickingDo::getOrderType, StaticDict.Stock_Pick_OrderType.Defective.getValue())
                    .eq(StockPickingDo::getWhId, entityDo.getWhId()).list();
            List<Long> subStockIds = pickingDos.stream().map(StockPickingDo::getSubStockId).collect(Collectors.toList());
            Map<Long, ProductStockRackDo> stockMap = productStockRackDao.selectBatchIds(subStockIds).stream().collect(Collectors.toMap(ProductStockRackDo::getId, i -> i));
            for (StockPickingDo pickingDo : pickingDos) {
                ProductStockRackDo rackDo = stockMap.get(pickingDo.getSubStockId());
                if (rackDo == null || rackDo.getLockQuantity() < pickingDo.getQuantity()) {
                    ProductDo productDo = productDao.selectById(pickingDo.getProductId());
                    throw new BizException(SysConstant.Sku_Stock_Error_Contact_Admin, productDo.getSku());
                }
                productStockRackDao.reLockStock(pickingDo.getSubStockId(), pickingDo.getQuantity());
            }
            stockPickingDao.updateDelete(entityDo.getId(), StaticDict.Stock_Pick_OrderType.Defective.getValue(), userId);
        }
    }



    @Override
    public Object detail(Map<String, Object> map) {
        List<DefectivePageDto> list = dao.list(map);
        if (list.isEmpty()) return null;
        DefectivePageDto entityDo =  list.get(0);
        DefectiveDetailRes res = new DefectiveDetailRes();
        BeanUtils.copyProperties(entityDo, res);
        List<FileRes> fileList = fileMoreService.getFileList(null, StaticDict.File_Type.Defective.getValue());
        res.setFiles(fileList);
        List<DefProductDto> products = defectiveProductDao.getProducts(entityDo.getId());
        //次品可用数量
        //库存可用数量

        List<SkuStockTotalDto> skuStockTotal = productStockService.getSkuStockTotal(new SkuPickQueryBo(Long.parseLong(map.get("tenantId").toString()),
                entityDo.getCompanyId(), 1, 1, entityDo.getWhId(), products.stream().map(DefProductDto::getProductId).distinct().collect(Collectors.toList())));
        Map<String, SkuStockTotalDto> boxMap = skuStockTotal.stream().collect(Collectors.toMap(i -> i.getProductId()+ "_____" + i.getStockAttribute(), i -> i));
        for (DefProductDto product : products) {
            SkuStockTotalDto skuStockPageDto = boxMap.get(product.getProductId() + "_____" + 1);
            if (skuStockPageDto != null) {
                product.setSkuCanUseQuantity(skuStockPageDto.getQuantity());
            }
        }
        res.setProducts(products);
        res.setProgress(this.setProgressList(entityDo, map.get("source").toString()));
        return res;
    }

    public List<OrProgressRes> setProgressList(DefectivePageDto res, String source) {
        List<OrProgressRes> progressList = new ArrayList<>();
        progressList.add(new OrProgressRes("create", "创建", res.getDefectiveNo(), res.getCreateTime(), res.getCreateByName()));
        if (res.getSubmitTime() != null) {
            progressList.add(new OrProgressRes("submit", "提交", res.getDefectiveNo(), res.getSubmitTime(), res.getSubmitByName()));
        }
        if ("wms".equals(source)) {
            if (res.getSubmitPickTime() != null) {
                progressList.add(new OrProgressRes("submitPick", "提交拣货", res.getDefectiveNo(), res.getSubmitPickTime(), res.getSubmitPickByName()));
            }
        }
        if ("wms".equals(source)) {
            if (res.getFinishPickTime() != null) {
                progressList.add(new OrProgressRes("finishPick", "完成拣货", res.getDefectiveNo(), res.getFinishPickTime(), res.getFinishPickByName()));
            }
        }
        if (StaticDict.Defective_Wms_Status.Fifth.getValue().equals(res.getStatus())) {
            progressList.add(new OrProgressRes("cancel", "取消", res.getDefectiveNo(), res.getCancelTime(), res.getCancelByName()));
        }
        else {
            progressList.add(new OrProgressRes("complete", "完成处理", res.getDefectiveNo(), res.getCompleteTime(), res.getCompleteByName()));
        }
        return progressList;
    }


    @Override
    public SingleResult pageInit(Long tenantId, String source) {
        Map<String, Object> result = new HashMap<>();
        List<Map<Object, Object>> orderReturnStatus = new ArrayList<>();
        if ("oms".equals(source)) {
            orderReturnStatus = StaticDict.getDefective_Oms_Status();
            result.put("warehouseList", warehouseService.getList(tenantId));
        }
        else if ("wms".equals(source)){
            orderReturnStatus = StaticDict.getDefective_Wms_Status();
            result.put("companyList", companyService.getCompanyList(null, tenantId, source));
        }
        Map<Object, Object> map = new HashMap<>();
        map.put("id", null);
        map.put("name", "全部");
        orderReturnStatus.add(0, map);
        result.put("defectiveStatus", orderReturnStatus);
        return SingleResult.success(result);
    }

    @Override
    public List<DefectivePageDto> getList(Map<String, Object> map) {
        return dao.list(map);
    }

    @Override
    public PageResult getListPage(Map<String, Object> map) {
        IPage<DefectivePageDto> page = pageInit(map);
        page = dao.list(page, map);
        PageResult result = new PageResult(page.getRecords(), (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());

        return result;
    }


    @Override
    public List<Map<String, Object>> statusStatistics(Map<String, Object> map) {
        map.remove("status");
        List<DefectivePageDto> list = dao.list(map);

        Map<Integer, List<DefectivePageDto>> collect = list.stream().filter(i -> i.getStatus() != null).collect(Collectors.groupingBy(DefectivePageDto::getStatus));
        List<Map<String, Object>> resultList = new ArrayList<>();
        if ("oms".equals(map.get("source"))) {
            for (StaticDict.Defective_Oms_Status value : StaticDict.Defective_Oms_Status.values()) {
                Map<String, Object> m = new HashMap<>();
                m.put("id", value.getValue());
                m.put("name", value.getText());
                m.put("sum", collect.get(value.getValue()) == null ? 0 : collect.get(value.getValue()).size());
                resultList.add(m);
            }
        }
        else if ("wms".equals(map.get("source"))) {
            for (StaticDict.Defective_Wms_Status value : StaticDict.Defective_Wms_Status.values()) {
                Map<String, Object> m = new HashMap<>();
                m.put("id", value.getValue());
                m.put("name", value.getText());
                m.put("sum", collect.get(value.getValue()) == null ? 0 : collect.get(value.getValue()).size());
                resultList.add(m);
            }
        }
        return resultList;
    }


    private IPage<DefectivePageDto> pageInit(Map<String, Object> map) {
        IPage<DefectivePageDto> page = new Page();
        page.setSize(map.get("pageSize") != null ? Long.parseLong(map.get("pageSize").toString()) : 10);
        page.setCurrent(map.get("current") != null ? Long.parseLong(map.get("current").toString()) : 1);
        return page;
    }


    /**
     * 提交拣货 单纯状态变化
     */
    @Override
    public void startPicking(StartPickReq req, Long userId, Long whId, Long tenantId) {
        DefectiveDo entityDo = dao.selectById(req.getId());
        if (entityDo == null || !Objects.equals(entityDo.getTenantId(), tenantId) || !Objects.equals(entityDo.getWhId(), whId)) {
            throw new BizException(SysConstant.No_Data);
        }
        if (!StaticDict.Defective_Oms_Status.Second.getValue().equals(entityDo.getOmsStatus()) && !StaticDict.Defective_Wms_Status.First.getValue().equals(entityDo.getWmsStatus())) {
            throw new BizException(SysConstant.NoPower);
        }
        entityDo.setWmsStatus(StaticDict.Defective_Wms_Status.Second.getValue());
        entityDo.setSubmitPickTime(new Date());
        entityDo.setSubmitPickBy(userId);
        dao.updateById(entityDo);
    }



    @Override
    public PickInfoRes queryPickingInfo(Long id, Long userId, Long whId, Long tenantId) {
        Map<String, Object> map = new HashMap<>();
        map.put("tenantId", tenantId);
        map.put("source", "wms");
        map.put("storageId", whId);
        map.put("id", id);
        List<DefectivePageDto> pageList = dao.list(map);
        if (pageList == null) return null;
        DefectivePageDto entityDo = pageList.get(0);
        if (entityDo == null) {
            throw new BizException(SysConstant.No_Data);
        }
        if (!StaticDict.Defective_Wms_Status.Second.getValue().equals(entityDo.getStatus())) {
            throw new BizException(SysConstant.NoPower);
        }
        PickInfoRes res = new PickInfoRes();
        BeanUtils.copyProperties(entityDo, res);

        List<DefProductDto> defProductList = defectiveProductDao.getProducts(id);
        List<StockPickDto> stockPickDtoList = stockPickingService.getStockPickDto(id, StaticDict.Stock_Pick_OrderType.Defective.getValue());
        Map<Long, List<StockPickDto>> skuPickMap = stockPickDtoList.stream().collect(Collectors.groupingBy(StockPickDto::getProductId));
        Map<Long, List<DefProductDto>> productAddMap = defProductList.stream().collect(Collectors.groupingBy(DefProductDto::getProductId));

        //库存可用数量
        List<SkuCellStockDto> boxCellStock = productStockDao.getSkuCellStock(new ArrayList<>(productAddMap.keySet()),
                stockPickDtoList.stream().map(StockPickDto::getRackId).distinct().collect(Collectors.toList())
                , Collections.singletonList(entityDo.getCompanyId()), 1, whId, tenantId);
        Map<String, SkuCellStockDto> boxMap = boxCellStock.stream().collect(Collectors.toMap(i -> i.getProductId()+ "_____" + i.getStockAttribute() + "_____" + i.getRackId()+ "_____" + i.getCompanyId(), i -> i));

        List<PickSkuInfoRes> skus = new ArrayList<>();
        for (Long productId : productAddMap.keySet()) {
            List<StockPickDto> pickingDos = skuPickMap.get(productId);
            if (pickingDos == null || pickingDos.isEmpty()) {
                throw new BizException(SysConstant.No_Data);
            }
            int quantity = pickingDos.stream().mapToInt(StockPickDto::getQuantity).sum();
            int hadPicked = pickingDos.stream().mapToInt(StockPickDto::getPickedQty).sum();
            if (quantity == hadPicked) continue;
            List<PickSkuRackInfo> skuRacks = new ArrayList<>();
            for (StockPickDto pickingDo : pickingDos) {
                SkuCellStockDto cellStock = boxMap.get(pickingDo.getProductId() + "_____" + 1 + "_____" + pickingDo.getRackId() + "_____" + entityDo.getCompanyId());
                int canUseQty = pickingDo.getQuantity() - pickingDo.getPickedQty();
                if (cellStock != null) {
                    canUseQty += cellStock.getQuantity();
                }
                PickSkuRackInfo rackInfo = new PickSkuRackInfo(pickingDo.getRackId(), pickingDo.getCellNo(), canUseQty, quantity - hadPicked);
                skuRacks.add(rackInfo);
            }

            PickSkuInfoRes sku = new PickSkuInfoRes(productAddMap.get(productId).get(0).getSku(), productId, productAddMap.get(productId).get(0).getProductName(),
                    quantity, hadPicked, skuRacks);
            skus.add(sku);
        }
        res.setSkus(skus);
        if (skus.isEmpty()) {
            DefectiveDo et = dao.selectById(id);
            et.setFinishPickTime(new Date());
            et.setFinishPickBy(userId);
            et.setWmsStatus(StaticDict.Defective_Wms_Status.Third.getValue());
            dao.updateById(et);
        }
        return res;
    }


    @Override
    public int submitPicking(PickInfoRes req, Long userId, Long whId, Long tenantId) {
        DefectiveDo et = dao.selectById(req.getId());
        if (!StaticDict.Defective_Wms_Status.Second.getValue().equals(et.getWmsStatus())) {
            throw new BizException(SysConstant.NoPower);
        }
        //原 应拣货数量
        List<StockPickDto> stockPickDtoList = stockPickingService.getStockPickDto(req.getId(), StaticDict.Stock_Pick_OrderType.Defective.getValue());
        Map<String, StockPickDto> skuPickMap = stockPickDtoList.stream().collect(Collectors.toMap(i -> i.getProductId() +"_" + i.getRackId(), i-> i));

        Map<String, List<StockPickingDo>> pickListMap = stockPickingService.lambdaQuery().eq(StockPickingDo::getOrderId, req.getId()).eq(StockPickingDo::getOrderType, StaticDict.Stock_Pick_OrderType.Defective.getValue()).list()
                .stream().collect(Collectors.groupingBy(i -> i.getProductId() + "_" + i.getRackId()));

        Map<Long, List<PickSkuInfoRes>> reqSkuMap = req.getSkus().stream().collect(Collectors.groupingBy(PickSkuInfoRes::getProductId));

        Map<Long, Map<Long, Integer>> productRackThisPickMap = new HashMap<>();
        for (Long productId : reqSkuMap.keySet()) {
            List<PickSkuInfoRes> pickSkuInfoRes = reqSkuMap.get(productId);
            Map<Long, Integer> map = new HashMap<>();//key rackId value quantity
            for (PickSkuInfoRes pickSkuInfoRe : pickSkuInfoRes) {
                for (PickSkuRackInfo rack : pickSkuInfoRe.getRacks()) {
                    if (rack.getThisPickQty() == 0) continue;
                    map.merge(rack.getRackId(), rack.getThisPickQty(), Integer::sum);
                }
            }
            //判断一下本次拣货数量是不是超了 应拣货数量
            int sum = stockPickDtoList.stream().filter(i -> i.getProductId().equals(productId)).mapToInt(i -> i.getQuantity() - i.getPickedQty()).sum();
            if (sum < map.values().stream().mapToInt(i -> i).sum()){
                throw new BizException(SysConstant.Sku_Count_Error, pickSkuInfoRes.get(0).getSku());
            }
            productRackThisPickMap.put(productId, map);
        }

        Map<Long, Integer> reLockMap = new HashMap<>();
        for (Long productId : reqSkuMap.keySet()) {
            Map<Long, Integer> map = productRackThisPickMap.get(productId);//key rackId value quantity

            //库存可用数量
            List<SkuCellStockDto> boxCellStock = productStockDao.getSkuCellStock(Arrays.asList(productId),
                    new ArrayList<>(map.keySet()), Collections.singletonList(et.getCompanyId()), 1, whId, tenantId);
            Map<Long, SkuCellStockDto> boxMap = boxCellStock.stream().collect(Collectors.toMap(SkuCellStockDto::getRackId, i -> i));

            //获取这个sku 库位上 的所有库存列表
            Map<Long, List<SkuStockForPickDto>> skuForPickMap = productStockService.getStockForPickList(new SkuPickQueryBo(tenantId, et.getCompanyId(), 1, 1, whId, Arrays.asList(productId), new ArrayList<>(map.keySet())))
                    .stream().collect(Collectors.groupingBy(SkuStockForPickDto::getRackId));
            for (Long rackId : map.keySet()) {
                int thisPickQty = map.get(rackId);
                StockPickDto stockPickDto = skuPickMap.get(productId + "_" + rackId);
                if (stockPickDto != null && (stockPickDto.getQuantity() - stockPickDto.getPickedQty() > 0)){
                    //正常去完成拣货就行
                    int max = Math.min(thisPickQty, stockPickDto.getQuantity() - stockPickDto.getPickedQty());
                    thisPickQty = Math.max(0, thisPickQty - max);
                    List<StockPickingDo> pickingDos = pickListMap.get(productId + "_" + rackId);
                    for (StockPickingDo pickingDo : pickingDos) {
                        if (Objects.equals(pickingDo.getQuantity(), pickingDo.getPickedQty())) continue;
                        if ((pickingDo.getQuantity() - pickingDo.getPickedQty()) >= max) {
                            pickingDo.setPickedQty(pickingDo.getPickedQty() + max);
                            max = 0;
                        }
                        else {
                            max -= (pickingDo.getQuantity() - pickingDo.getPickedQty());
                            pickingDo.setPickedQty(pickingDo.getQuantity());
                        }
                        stockPickingDao.updateById(pickingDo);
                        if (max == 0) {
                            break;
                        }
                    }
                }
                if (thisPickQty > 0) {
                    //原锁定库位库存不足 需要添加新的  意味着 有旧的需要解除锁定
                    reLockMap.merge(productId, thisPickQty, Integer::sum);
                    SkuCellStockDto nowSkuStock = boxMap.get(rackId);
                    if (nowSkuStock == null || nowSkuStock.getQuantity() < thisPickQty) {
                        throw new BizException(SysConstant.Sku_Stock_NotEnough, productId);
                    }
                    //添加新的锁定记录 并且添加锁定库存
                    //按照库位优先级，先进先出 获取库存列表
                    List<StockPickingDo> pickingList = new ArrayList<>();
                    int quantity = thisPickQty;
                    for (SkuStockForPickDto i : skuForPickMap.get(rackId)) {
                        if (i.getQuantity() <= 0) continue;
                        int lockQty = 0;
                        if (i.getQuantity() > quantity) {
                            lockQty = quantity;
                            quantity = 0;
                        } else {
                            lockQty = i.getQuantity();
                            quantity -= lockQty;
                        }
                        if (lockQty == 0) {
                            continue;
                        }
                        i.setQuantity(i.getQuantity() - lockQty);
                        productStockRackDao.lockStock(i.getStockId(), lockQty);
                        //添加到锁定记录
                        StockPickingDo pickingDo = new StockPickingDo(et.getCompanyId(), whId, et.getId(),
                                StaticDict.Stock_Pick_OrderType.Defective.getValue(), "sku", i.getProductId(), i.getRackId(), i.getStockId(), lockQty, lockQty);
                        pickingList.add(pickingDo);
                    }
                    if (quantity > 0) {
                        throw new BizException(SysConstant.Sku_Stock_NotEnough, reqSkuMap.get(productId).get(0).getSku());
                    }
                    stockPickingService.insertBatch(pickingList);
                }
            }
            //根据id 获取锁定表 记录 根据库位优先级排序
            List<StockPickListDto> pickList = stockPickingDao.getNoFinishPickList(et.getId(), StaticDict.Stock_Pick_OrderType.Defective.getValue());
            List<Long> subStockId = pickList.stream().filter(i -> reLockMap.containsKey(i.getProductId())).map(StockPickListDto::getSubStockId).distinct().collect(Collectors.toList());
            Map<Long, ProductStockRackDo> stockRackMap = new HashMap<>();
            if (!subStockId.isEmpty()) {
                List<ProductStockRackDo> stockRackDos = productStockRackDao.selectBatchIds(subStockId);
                stockRackMap = stockRackDos.stream().collect(Collectors.toMap(ProductStockRackDo::getId, i -> i));
            }
            for (Long key : reLockMap.keySet()) {
                //解锁库存 并stockPick 减少数量
                int quantity = reLockMap.get(key);
                for (StockPickListDto stockPickListDto : pickList) {
                    if (!Objects.equals(stockPickListDto.getProductId(), key)) continue;
                    int reQty = 0;
                    if ((stockPickListDto.getQuantity() - stockPickListDto.getPickedQty()) >= quantity) {
                        reQty = quantity;
                        quantity = 0;
                    }
                    else {
                        reQty = (stockPickListDto.getQuantity() - stockPickListDto.getPickedQty());
                        quantity -= (stockPickListDto.getQuantity() - stockPickListDto.getPickedQty());
                    }

                    ProductStockRackDo rackDo = stockRackMap.get(stockPickListDto.getSubStockId());
                    if (rackDo == null || rackDo.getLockQuantity() < reQty) {
                        throw new BizException(SysConstant.Sku_Stock_NotEnough, key);
                    }
                    rackDo.setLockQuantity(rackDo.getLockQuantity() - reQty);
                    rackDo.setQuantity(rackDo.getQuantity() + reQty);
                    productStockRackDao.updateById(rackDo);
                    stockPickingDao.updateQty(stockPickListDto.getId(), reQty);

                    if (quantity == 0) {
                        break;
                    }
                }
                if (quantity > 0) {
                    ProductDo productDo = productDao.selectById(key);
                    throw new BizException(SysConstant.Sku_Stock_NotEnough, productDo.getSku());
                }
            }
        }
        List<StockPickListDto> pickList = stockPickingDao.getNoFinishPickList(et.getId(), StaticDict.Stock_Pick_OrderType.Defective.getValue());
        if (pickList.isEmpty()) {
            et.setFinishPickTime(new Date());
            et.setFinishPickBy(userId);
            et.setWmsStatus(StaticDict.Defective_Wms_Status.Third.getValue());
            dao.updateById(et);
        }
        return pickList.size();
    }


    /**
     * 翻新上架 - 处理中
     */
    @Override
    public SubmitShelfInitRes submitShelfInit(Long id, Long userId, Long whId, Long tenantId) {
        Map<String, Object> map = new HashMap<>();
        map.put("tenantId", tenantId);
        map.put("source", "wms");
        map.put("storageId", whId);
        map.put("id", id);
        List<DefectivePageDto> pageList = dao.list(map);
        if (pageList == null) return null;
        DefectivePageDto entityDo = pageList.get(0);
        if (entityDo == null) {
            throw new BizException(SysConstant.No_Data);
        }
        if (!StaticDict.Defective_Wms_Status.Third.getValue().equals(entityDo.getStatus())) {
            throw new BizException(SysConstant.NoPower);
        }
        SubmitShelfInitRes res = new SubmitShelfInitRes();
        BeanUtils.copyProperties(entityDo, res);
        List<DefProductDto> defProductList = defectiveProductDao.getProducts(id);
        List<SubmitShelfSkuRes> skus = new ArrayList<>();
        Map<Long, List<DefProductDto>> productAddMap = defProductList.stream().collect(Collectors.groupingBy(DefProductDto::getProductId));
        for (Long productId : productAddMap.keySet()) {
            SubmitShelfSkuRes skuRes = new SubmitShelfSkuRes();
            skuRes.setProductId(productId);
            skuRes.setSku(productAddMap.get(productId).get(0).getSku());
            skuRes.setProductName(productAddMap.get(productId).get(0).getProductName());
            skuRes.setHadPickQty(productAddMap.get(productId).stream().mapToInt(DefProductDto::getQuantity).sum());
            //已上架数量
            int putQty = productStockDao.getPutQty(productId, entityDo.getId(), StockOrderTypeEnum.Defective.getValue(), entityDo.getCompanyId());
            skuRes.setHadPutQty(putQty);
            if (skuRes.getHadPickQty() == skuRes.getHadPutQty()) {
                continue;
            }
            //获取推荐库位
            LocationRes pickingRecommendRack = storageLocationService.getPickingRecommendRack(0, whId);

            List<SubmitShelfSkuRackRes> racks = new ArrayList<>();
            racks.add(new SubmitShelfSkuRackRes(pickingRecommendRack == null ? null : pickingRecommendRack.getId(),
                    pickingRecommendRack == null ? null : pickingRecommendRack.getCellNo(), skuRes.getHadPickQty() - skuRes.getHadPutQty()));
            skuRes.setRacks(racks);
            skus.add(skuRes);
        }
        res.setSkus(skus);
        if (skus.isEmpty()) {
            // 变更为 已完成
            this.lambdaUpdate().eq(DefectiveDo::getId, entityDo.getId())
                    .set(DefectiveDo::getOmsStatus, StaticDict.Defective_Oms_Status.Third.getValue())
                    .set(DefectiveDo::getWmsStatus, StaticDict.Defective_Wms_Status.Fourth.getValue())
                    .set(DefectiveDo::getCompleteTime, new Date())
                    .set(DefectiveDo::getCompleteBy, userId).update();
        }

        return res;


    }


    /**
     * 上架
     */
    @Override
    public int submitShelf(SubmitShelfInitRes req, Long userId, Long whId, Long tenantId) {
        DefectiveDo et = dao.selectById(req.getId());
        if (!StaticDict.Defective_Wms_Status.Third.getValue().equals(et.getWmsStatus())) {
            throw new BizException(SysConstant.NoPower);
        }
        //获取次品处理子表，并根据productId分类
        List<DefProductDto> defProductList = defectiveProductDao.getProducts(req.getId());
        Map<Long, List<DefProductDto>> productAddMap = defProductList.stream().collect(Collectors.groupingBy(DefProductDto::getProductId));
        //请求过来的上架列表
        Map<Long, List<SubmitShelfSkuRes>> skuReqMap = req.getSkus().stream().collect(Collectors.groupingBy(SubmitShelfSkuRes::getProductId));

        //获取未上架完成的 pick记录
        List<StockPickListDto> pickList = stockPickingDao.getNoOutList(et.getId(), StaticDict.Stock_Pick_OrderType.Defective.getValue());
        Map<Long, Integer> putQtyMap = new HashMap<>();
        for (Long productId : productAddMap.keySet()) {
            List<SubmitShelfSkuRes> skuReqList = skuReqMap.get(productId);
            if (skuReqList == null || skuReqList.isEmpty()) {
                continue;
            }
            //本次要上架的数量
            int putQty = skuReqList.stream().mapToInt(i -> i.getRacks().stream().filter(z -> z.getThisSubmitQty() > 0 && z.getRackId() != null).mapToInt(SubmitShelfSkuRackRes::getThisSubmitQty).sum()).sum();
            putQty = Math.max(0, putQty);
            if (putQty > 0) {
                //可上架数量
                int canPutQty = pickList.stream().filter(i -> Objects.equals(i.getProductId(), productId)).mapToInt(i -> i.getPickedQty() - i.getOutQty()).sum();
                if (canPutQty < putQty) {
                    throw new BizException(SysConstant.Sku_Stock_NotEnough, skuReqList.get(0).getSku());
                }
            }
            putQtyMap.put(productId, putQty);
        }
        for (Long productId : productAddMap.keySet()) {
            List<SubmitShelfSkuRes> skuReqList = skuReqMap.get(productId);
            if (skuReqList == null) {
                continue;
            }
            //先去上架 并减去锁定次品库存
            Integer putQty = putQtyMap.get(productId);
            if (putQty == null || putQty == 0) {
                continue;
            }
            for (StockPickListDto stockPickListDto : pickList) {
                if (!Objects.equals(stockPickListDto.getProductId(), productId)) {
                    continue;
                }
                int outQty = 0;
                if ((stockPickListDto.getPickedQty() - stockPickListDto.getOutQty()) > putQty) {
                    outQty = putQty;
                    putQty = 0;
                } else {
                    outQty = stockPickListDto.getPickedQty() - stockPickListDto.getOutQty();
                    putQty -= outQty;
                }
                if (stockPickListDto.getSubStockLockQuantity() < stockPickListDto.getPickedQty()) {
                    throw new BizException(SysConstant.Sku_Stock_Error_Contact_Admin, stockPickListDto.getSku());
                }
                stockPickingDao.updatePutQty(stockPickListDto.getId(), outQty);
                productStockRackDao.reduceBadLockStock(stockPickListDto.getSubStockId(), outQty);
                //库存流水
                productStockFlowingService.insertProForIn(ProductFlowingInEt.builder().sku(stockPickListDto.getSku()).companyId(et.getCompanyId())
                        .warehouseId(whId).rackId(stockPickListDto.getRackId()).stockAttribute(1)
                        .bookQuantity(-outQty).orderType(StockOrderTypeEnum.Defective.getValue()).noteNo(et.getDefectiveNo())
                        .tenantId(tenantId).type(StockTypeEnum.one.getValue())
                        .build());
                if (putQty == 0) {
                    break;
                }
            }
            if (putQty > 0) {
                throw new BizException(SysConstant.Sku_Stock_NotEnough, productId);
            }

            for (SubmitShelfSkuRes skuRes : skuReqList) {
                for (SubmitShelfSkuRackRes rack : skuRes.getRacks()) {
                    if (rack.getRackId() == null || rack.getThisSubmitQty() == 0) continue;
                    ProductStockDo stockDo = new ProductStockDo(et.getCompanyId(), whId, StockOrderTypeEnum.Defective.getValue(), et.getId(), skuRes.getProductId(), rack.getThisSubmitQty(), StockTypeEnum.one.getValue(), tenantId);
                    productStockDao.insert(stockDo);
                    ProductStockRackDo rackDo = new ProductStockRackDo(stockDo.getId(), rack.getRackId(), 0, rack.getThisSubmitQty(), rack.getThisSubmitQty());
                    productStockRackDao.insert(rackDo);

                    //库存流水
                    productStockFlowingService.insertProForIn(ProductFlowingInEt.builder().sku(skuRes.getSku()).companyId(et.getCompanyId())
                            .warehouseId(whId).rackId(rack.getRackId()).stockAttribute(0)
                            .bookQuantity(rack.getThisSubmitQty()).orderType(StockOrderTypeEnum.Defective.getValue()).noteNo(et.getDefectiveNo())
                            .tenantId(tenantId).type(StockTypeEnum.one.getValue())
                            .build());
                }
            }
        }

        pickList = stockPickingDao.getNoOutList(et.getId(), StaticDict.Stock_Pick_OrderType.Defective.getValue());
        if (pickList.isEmpty()) {
            et.setCompleteTime(new Date());
            et.setCompleteBy(userId);
            et.setOmsStatus(StaticDict.Defective_Oms_Status.Third.getValue());
            et.setWmsStatus(StaticDict.Defective_Wms_Status.Fourth.getValue());
            dao.updateById(et);
        }
        return pickList.size();
    }

    /**
     * 确认出库 确认销毁
     */
    @Override
    public void submitOut(StartPickReq req, Long userId, Long whId, Long tenantId) {
        DefectiveDo et = dao.selectById(req.getId());
        if (!StaticDict.Defective_Wms_Status.Third.getValue().equals(et.getWmsStatus())) {
            throw new BizException(SysConstant.NoPower);
        }
        List<Integer> handleMethodList = Arrays.asList(1, 2);
        if (!handleMethodList.contains(et.getHandleMethod())) {
            throw new BizException(SysConstant.NoPower);
        }

        List<StockPickListDto> pickList = stockPickingDao.getNoOutList(et.getId(), StaticDict.Stock_Pick_OrderType.Defective.getValue());
        for (StockPickListDto stockPickListDto : pickList) {
            if (stockPickListDto.getSubStockLockQuantity() < stockPickListDto.getPickedQty()) {
                throw new BizException(SysConstant.Sku_Stock_NotEnough, stockPickListDto.getSku());
            }
            stockPickingDao.updatePutQty(stockPickListDto.getId(), stockPickListDto.getPickedQty());
            productStockRackDao.reduceBadLockStock(stockPickListDto.getSubStockId(), stockPickListDto.getPickedQty());
            //库存流水
            productStockFlowingService.insertProForOut(ProductFlowingOutEt.builder().sku(stockPickListDto.getSku()).companyId(et.getCompanyId())
                    .warehouseId(whId).rackId(stockPickListDto.getRackId()).stockAttribute(1)
                    .bookQuantity(-stockPickListDto.getPickedQty()).orderType(StockOrderTypeEnum.Defective.getValue()).noteNo(et.getDefectiveNo())
                    .tenantId(tenantId).type(StockTypeEnum.one.getValue())
                    .build());
        }
        et.setOmsStatus(StaticDict.Defective_Oms_Status.Third.getValue());
        et.setWmsStatus(StaticDict.Defective_Wms_Status.Fourth.getValue());
        et.setCompleteTime(new Date());
        et.setCompleteBy(userId);
        dao.updateById(et);
    }

    @Override
    public void printPick(Map<String, Object> map, HttpServletResponse response) throws Exception {
        response.setHeader("Content-Type", "application/pdf");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setHeader("Content-Disposition", "attachment;filename=shelfPrint.pdf");
        List<DefectivePageDto> list = dao.list(map);
        if (list.isEmpty()) throw new BizException(SysConstant.No_Data);
        DefectivePageDto entityDo =  list.get(0);
        //通用参数
        byte[] pasNoBarcode = BarCodeUtils.generateBarCode128(
                entityDo.getDefectiveNo(), false, false, 256, 15, 0.3f, 0f, 0f
        );
        ByteArrayInputStream pasNoBarcodeImg = new ByteArrayInputStream(pasNoBarcode);
        Map<String, Object> data = new HashMap<>(16);
        data.put("defectiveNo", entityDo.getDefectiveNo());
        data.put("client", entityDo.getCompanyName()+"("+entityDo.getCompanyCode()+")");
        data.put("handleMethod", entityDo.getHandleMethodName());
        data.put("printTime", DateUtil.date());
        data.put("defectiveNoBarcode", Pictures.ofStream(pasNoBarcodeImg, PictureType.PNG).size(245, 70).create());
        List<StockPickDto> pickDtoList = stockPickingDao.getPickDto(entityDo.getId(), StaticDict.Stock_Pick_OrderType.Defective.getValue());
        List<DefectiveTableDto> skuList = new ArrayList<>();
        Map<Long, List<StockPickDto>> piclMap = pickDtoList.stream().collect(Collectors.groupingBy(StockPickDto::getProductId));
        data.put("skuKind", piclMap.keySet().size());
        data.put("skuTotalQty", pickDtoList.stream().mapToInt(StockPickDto::getQuantity).sum());
        data.put("tips", entityDo.getTips());

        AtomicInteger i = new AtomicInteger(1);
        for (Long productId : piclMap.keySet()) {
            StockPickDto pickDto = piclMap.get(productId).get(0);
            DefectiveTableDto dto = new DefectiveTableDto(String.valueOf(i.getAndIncrement()), pickDto.getSku(),
                    pickDto.getMainBarcode(), pickDto.getProductName(),
                    piclMap.get(productId).stream().mapToInt(StockPickDto::getQuantity).sum()+"");

            for (StockPickDto stockPickDto : piclMap.get(productId)) {
                HashMap<String, String> sonMap = new HashMap<>(4);
                sonMap.put("cellCode", stockPickDto.getCellNo());
                sonMap.put("cellQty", stockPickDto.getPickedQty() +" / "+stockPickDto.getQuantity());
                dto.getSonList().add(sonMap);
            }
            skuList.add(dto);
        }
        data.put("table", this.getDefectivePrintTableData(skuList, new DynamicTableDto(0, 0, 5, 7, 1)));
        Resource resource;
        File templateFile;
        ConfigureBuilder configureBuilder = Configure.builder();
        XWPFTemplate template;
        ByteArrayOutputStream pdf;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ServletOutputStream out = response.getOutputStream();
        //获取模板文件
//        resource = new ClassPathResource("wordTemplates/defective-pick.docx");
//        templateFile = resource.getFile();
//        templateFile = new File(localPath + File.separator + "defective-pick.docx");
        //模板配置
        configureBuilder.bind("table", new DynamicTablePolicy());
//        template = XWPFTemplate.compile(templateFile, configureBuilder.build()).render(data);
        template = XWPFTemplate.compile(this.getClass().getClassLoader().getResourceAsStream("wordTemplates/defective-pick.docx"), configureBuilder.build()).render(data);
        template.writeAndClose(bos);
        //转换为pdf
        pdf = AsposePdfUtils.word2pdf(new ByteArrayInputStream(bos.toByteArray()));
        out.write(pdf.toByteArray());
        bos.flush();
        out.flush();
        PoitlIOUtils.closeQuietlyMulti(template, bos, out, pdf);

    }

    private DynamicTableDto getDefectivePrintTableData(List<DefectiveTableDto> dtoList, DynamicTableDto dynamicTableDto) {
        for (DefectiveTableDto dto : dtoList) {
            dynamicTableDto.getGroupMap().put(dto.getNo(), dto.getSonList().size());
            byte[] boxBarcode = BarCodeUtils.generateBarCode128(dto.getSku(), false, false, 256, 15, 0.4f, 0, 0);
            ByteArrayInputStream boxBarcodeImg = new ByteArrayInputStream(boxBarcode);
            for (Map<String, String> sonMap : dto.getSonList()) {
                RowRenderData rowRenderData = Rows.of(
                        Cells.of(dto.getNo()).create(),
                        Cells.of(dto.getSku()).create(),
                        Cells.of(Pictures.ofStream(boxBarcodeImg, PictureType.PNG).size(190, 55).create()).create(),
                        Cells.of(dto.getProductName()).create(),
                        Cells.of(dto.getQty()).create(),
                        Cells.of(sonMap.get("cellCode")).create(),
                        Cells.of(sonMap.get("cellQty")).create()
                ).center().create();
                dynamicTableDto.getDataList().add(rowRenderData);
            }
        }
        return dynamicTableDto;
    }
}
